package client;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;

public class JPEGEncoderThread implements Runnable {
	private Thread thread;
	private JPEGEncodeParam encodingParameters;
	private ImageEncoder imageEncoder;
	private BufferedImage image;
	private boolean isComplete = false;
	
	private static int[] lowQuality = new int[] {64, 44, 40, 64, 96, 160, 204, 244,
												 48, 48, 56, 76, 104, 232, 240, 220,
												 56, 52, 64, 96, 160, 228, 276, 224,
											     56, 68, 88, 116, 204, 100, 100, 100,
											     72, 88, 148, 100, 100, 100, 100, 100,
											     96, 140, 220, 100, 100, 100, 100, 100,
											     196, 256, 100, 100, 100, 100, 100, 100,
												 288, 100, 100, 100, 100, 100 ,100, 100};
	
	private static int[] goodQuality = new int[] {32, 22, 20, 32, 48, 80, 102, 122,
												  24, 24, 28, 38, 52, 116, 120, 110,
												  28, 28, 32, 48, 80, 114, 138, 112,
												  28, 34, 44, 58, 102, 50, 50, 124,
												  36, 44, 74, 50, 50, 50, 50 ,50,
												  48, 70, 110, 50, 50, 50, 50, 50,
												  98, 128, 50, 50, 50, 50, 50, 50,
												  144, 50, 50, 50, 50, 50, 50, 50};
	
	private static int[] fineQuality = new int[] {4, 2, 2, 4, 6, 10, 12, 15,
												  3, 3, 3, 4, 6, 14, 15, 13,
												  3, 3, 4, 6, 10, 14, 17, 14,
												  3, 4, 5, 7, 12, 21, 20, 15,
												  4, 5, 9, 14, 17, 27, 25, 19,
												  6, 8, 13, 16, 20, 26, 28, 23,
												  12, 16, 19, 21, 25, 30, 30, 25,
												  18, 23, 23, 24, 28, 25, 25, 24};
	
	private static int[] proQuality = new int[] {1, 1, 1, 1, 1, 1, 1, 2,
											     1, 1, 1, 1, 1, 1, 1, 2,
												 1, 1, 1, 1, 1, 1, 2, 2,
												 1, 1, 1, 1, 1, 2, 2, 3,
											     1, 1, 1, 1, 2, 2, 3, 3,
											     1, 1, 1, 2, 2, 3, 3, 3,
											     1, 1, 2, 2, 3, 3, 3, 3,
												 2, 2, 2, 3, 3, 3, 3, 3};
	public static final int LOW_QUALITY = 0;
	public static final int GOOD_QUALITY = 1;
	public static final int FINE_QUALITY = 2;
	public static final int PRO_QUALITY = 3;
	
	public JPEGEncoderThread(BufferedImage image, int qualityLevel){
		encodingParameters = new JPEGEncodeParam();
		this.image = image;
		switch(qualityLevel){
			case JPEGEncoderThread.LOW_QUALITY:
				/* Set Quantization Tables */
				encodingParameters.setChromaQTable(JPEGEncoderThread.lowQuality);
				encodingParameters.setLumaQTable(JPEGEncoderThread.lowQuality);
				
				/* Set Sub Sampling Levels */
				
			break;
			
			case JPEGEncoderThread.GOOD_QUALITY:
				/* Set Quantization Tables */
				encodingParameters.setChromaQTable(JPEGEncoderThread.goodQuality);
				encodingParameters.setLumaQTable(JPEGEncoderThread.goodQuality);
				
				/* Set Sub Sampling Levels */
			break;
			
			case JPEGEncoderThread.FINE_QUALITY:
				/* Set Quantization Tables */
				encodingParameters.setChromaQTable(JPEGEncoderThread.fineQuality);
				
				/* Set Sub Sampling Levels */
			break;
			
			case JPEGEncoderThread.PRO_QUALITY:
				/* Set Quantization Tables */
				encodingParameters.setChromaQTable(JPEGEncoderThread.proQuality);
				
				/* Set Sub Sampling Levels */
			break;
			
			default:
				/* If default, then use fine quality setting (Might as well give em something nice! =)) */
				/* Set Quantization Tables */
				encodingParameters.setChromaQTable(JPEGEncoderThread.fineQuality);
				
				/* Set Sub Sampling Levels */
			break;
		}
		
		try {
			imageEncoder = ImageCodec.createImageEncoder("JPEG", new FileOutputStream(new File("tmp/Image" + qualityLevel + ".jpg")), encodingParameters);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
		/* Create the Thread a begin it running */
		thread = new Thread(this, "JPEG Encoding Thread");
		//thread.start();
		this.run();
	}
	
	public void run(){
		try {
			imageEncoder.encode(image);
			isComplete = !isComplete;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public synchronized boolean isComplete(){
		if(!isComplete){
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			notifyAll();
		}
		return isComplete;
	}
}
